import os
import sys
import tkinter as tk
from tkinter import filedialog, messagebox

# Ruta fija al directorio de los TXT
script_dir = os.path.dirname(os.path.abspath(__file__))  # ubicación del script

 
bin_dir = os.path.normpath(os.path.join(script_dir, "..", "..", "binarios"))  # sube dos niveles y entra en binarios
txts_dir = os.path.join(bin_dir, "txts")
#print (txts_dir)
#sys.exit()

# Dirección inicial
direccion_memoria_inicial = 49152

# Obtener lista de nombres de archivos TXT sin extensión
txt_files = sorted([os.path.splitext(f)[0] for f in os.listdir(txts_dir) if f.endswith(".txt")])

def add_to_selected():
    selected = listbox_left.curselection()
    for i in selected:
        item = listbox_left.get(i)
        if item not in listbox_right.get(0, tk.END):
            listbox_right.insert(tk.END, item)

def remove_from_selected():
    selected = listbox_right.curselection()
    for i in reversed(selected):
        listbox_right.delete(i)

def generate_combined_bin():
    selected_files = listbox_right.get(0, tk.END)
    if not selected_files:
        messagebox.showwarning("Advertencia", "No hay archivos seleccionados.")
        return

    output_file = filedialog.asksaveasfilename(defaultextension=".bin", filetypes=[("Archivo binario", "*.bin")])
    if not output_file:
        return

    try:
        with open(output_file, "wb") as outfile_bin:
            code_txt_path = os.path.join(os.path.dirname(output_file), "defBloqueCodigo.txt")
            with open(code_txt_path, "w", encoding="utf-8") as outfile_txt:

                direccion_memoria = direccion_memoria_inicial

                for name in selected_files:
                    bin_path = os.path.join(bin_dir, name + ".bin")
                    txt_path = os.path.join(txts_dir, name + ".txt")

                    if os.path.exists(bin_path):
                        with open(bin_path, "rb") as infile:
                            outfile_bin.write(infile.read())
                    else:
                        messagebox.showerror("Error", f"No se encontró el archivo bin: {bin_path}")
                        return

                    if os.path.exists(txt_path):
                        with open(txt_path, "r", encoding="utf-8") as txtfile:
                            incremento = 0
                            lineas = txtfile.readlines()

                            # Saltar primera línea
                            for line in lineas[1:]:
                                line = line.strip()
                                if not line:
                                    continue  # Saltar vacías

                                partes = line.split()
                                if len(partes) == 3:
                                    posicion_local_str, longitud,texto = partes
                                    incremento = int(longitud)
                                else:
                                    posicion_local = int(partes[0])
                                    texto = ""
                                
                                # Escribir primero
                                #nueva_linea = f"{direccion_memoria}".ljust(24) + texto + "\n"
                                nueva_linea = f"#DEFINE {texto} {direccion_memoria}\n"
                                outfile_txt.write(nueva_linea)
                                direccion_memoria += incremento
                                
                    else:
                        messagebox.showerror("Error", f"No se encontró el archivo TXT: {txt_path}")
                        return

        messagebox.showinfo("Éxito", f"Archivo bin combinado guardado como:\n{output_file}\n"
                                     f"Archivo de texto combinado guardado como:\n{code_txt_path}")
    except Exception as e:
        messagebox.showerror("Error", f"Ocurrió un error:\n{e}")

def generate_ramdisk_bin():
    selected_files = listbox_right.get(0, tk.END)
    if not selected_files:
        messagebox.showwarning("Advertencia", "No hay archivos seleccionados.")
        return

    output_file = filedialog.asksaveasfilename(defaultextension=".bin", filetypes=[("Archivo binario", "*.bin")])
    if not output_file:
        return

    try:
        with open(output_file, "wb") as outfile_bin:
            # Agregar ceros al principio del archivo
            offset = direccion_memoria_inicial - 49152
            if offset < 0:
                messagebox.showerror("Error", f"La dirección inicial ({direccion_memoria_inicial}) es menor que 49152.")
                return
            outfile_bin.write(b'\x00' * offset)

            code_txt_path = os.path.join(os.path.dirname(output_file), "defBloqueCodigo.txt")
            with open(code_txt_path, "w", encoding="utf-8") as outfile_txt:

                direccion_memoria = direccion_memoria_inicial

                for name in selected_files:
                    bin_path = os.path.join(bin_dir, name + ".bin")
                    txt_path = os.path.join(txts_dir, name + ".txt")

                    if os.path.exists(bin_path):
                        with open(bin_path, "rb") as infile:
                            outfile_bin.write(infile.read())
                    else:
                        messagebox.showerror("Error", f"No se encontró el archivo bin: {bin_path}")
                        return

                    if os.path.exists(txt_path):
                        with open(txt_path, "r", encoding="utf-8") as txtfile:
                            incremento = 0
                            lineas = txtfile.readlines()

                            for line in lineas[1:]:
                                line = line.strip()
                                if not line:
                                    continue

                                partes = line.split()
                                if len(partes) == 3:
                                    _, longitud, texto = partes
                                    incremento = int(longitud)
                                else:
                                    _, texto = partes[0], ""

                                nueva_linea = f"#DEFINE {texto} {direccion_memoria}\n"
                                outfile_txt.write(nueva_linea)
                                direccion_memoria += incremento
                    else:
                        messagebox.showerror("Error", f"No se encontró el archivo TXT: {txt_path}")
                        return

        messagebox.showinfo("Éxito", f"Archivo RAMDisk guardado como:\n{output_file}\n"
                                     f"Archivo de texto combinado guardado como:\n{code_txt_path}")
    except Exception as e:
        messagebox.showerror("Error", f"Ocurrió un error:\n{e}")






def guardar_lista_cfg():
    items = listbox_right.get(0, tk.END)
    if not items:
        messagebox.showwarning("Advertencia", "No hay archivos para guardar.")
        return

    i = 1
    while True:
        nombre_cfg = f"lista_{i:03d}.cfg"
        ruta_cfg = os.path.join(txts_dir, nombre_cfg)
        if not os.path.exists(ruta_cfg):
            break
        i += 1

    with open(ruta_cfg, "w") as f:
        for item in items:
            f.write(item + "\n")

    messagebox.showinfo("Guardado", f"Lista guardada en:\n{ruta_cfg}")

def cargar_lista_cfg():
    ruta_cfg = filedialog.askopenfilename(initialdir=script_dir, title="Seleccionar lista",
    filetypes=[("Archivo CFG", "*.cfg")])
    if not ruta_cfg:
        return

    try:
        with open(ruta_cfg, "r") as f:
            items = [line.strip() for line in f.readlines() if line.strip()]
        listbox_right.delete(0, tk.END)
        for item in items:
            listbox_right.insert(tk.END, item)
    except Exception as e:
        messagebox.showerror("Error", f"No se pudo cargar el archivo:\n{e}")


# Interfaz gráfica
root = tk.Tk()
root.title("Combinar archivos .bin")

frame = tk.Frame(root)
frame.pack(padx=10, pady=10)

# Lista izquierda
listbox_left = tk.Listbox(frame, selectmode=tk.MULTIPLE, width=40, height=20)
for f in txt_files:
    listbox_left.insert(tk.END, f)
listbox_left.grid(row=0, column=0)

# Botones entre listas
buttons_frame = tk.Frame(frame)
buttons_frame.grid(row=0, column=1, padx=5)
tk.Button(buttons_frame, text="→", command=add_to_selected).pack(pady=5)
tk.Button(buttons_frame, text="←", command=remove_from_selected).pack(pady=5)

# Lista derecha
listbox_right = tk.Listbox(frame, selectmode=tk.SINGLE, width=40, height=20)
listbox_right.grid(row=0, column=2)

# Botones inferiores
bottom_frame = tk.Frame(root)
bottom_frame.pack(pady=10)

tk.Button(bottom_frame, text="Generar bin combinado", command=generate_combined_bin).grid(row=0, column=0, padx=5)
tk.Button(bottom_frame, text="Guardar lista", command=guardar_lista_cfg).grid(row=0, column=1, padx=5)
tk.Button(bottom_frame, text="Cargar lista", command=cargar_lista_cfg).grid(row=0, column=2, padx=5)
tk.Button(bottom_frame, text="Generar RAMDisk", command=generate_ramdisk_bin).grid(row=0, column=3, padx=5)

root.mainloop()